﻿/*========================== 
 * @author 郑金泉
 * @desc 字符串实用工具
 * ========================= */
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Obsidian.Utils
{
    public class StringUtil
    {

        private Dictionary<string, bool> dictDistinctStr = new Dictionary<string, bool>(
            StringComparer.OrdinalIgnoreCase);

        public string DistinctString(int length)
        {
            string str;
            do { str = CreateRandomCode(length); }
            while (dictDistinctStr.ContainsKey(str));
            dictDistinctStr.Add(str, true);
            return str;
        }

        /// <summary>
        /// 剪切字符长度
        /// </summary>
        /// <param name="str">原字符</param>
        /// <param name="length">剪切长度</param>
        /// <param name="apostrophes">省略符</param>
        /// <returns>结果字符</returns>
        public static string Truncate(string str, int length, string apostrophes)
        {
            return str.Length > length ? str.Substring(0, length) + apostrophes : str;
        }

        /// <summary>
        /// 密码MD5加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Md5Encrypt(string str)
        {
            byte[] b = Encoding.UTF8.GetBytes(str);
            b = new MD5CryptoServiceProvider().ComputeHash(b);
            string ret = string.Empty;
            for (int i = 0; i < b.Length; i++)
                ret += b[i].ToString("x").PadLeft(2, '0');
            return ret;
        }

        /// <summary>
        /// URL编码
        /// </summary>
        /// <param name="str">原字符</param>
        /// <param name="encodingName">编码名称</param>
        /// <returns>结果字符</returns>
        public static string UrlEncode(string str, string encodingName)
        {
            byte[] bs = Encoding.GetEncoding(encodingName).GetBytes(str);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bs.Length; i++)
            {
                if (bs[i] < 128)
                    sb.Append((char)bs[i]);
                else
                {
                    sb.Append("%" + bs[i++].ToString("x").PadLeft(2, '0'));
                    sb.Append("%" + bs[i].ToString("x").PadLeft(2, '0'));
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转换为半角
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToDbcCase(string s)
        {
            if (s == null || s.Trim() == string.Empty) return s;

            StringBuilder sb = new StringBuilder(s.Length);
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == '\u3000')
                    sb.Append('\u0020');
                else if (IsSbcCase(s[i]))
                    sb.Append((char)((int)s[i] - 65248));
                else
                    sb.Append(s[i]);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 判断是否是半角
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsDbcCase(char c)
        {
            int i = (int)c;
            return i >= 32 && i <= 126;
        }

        /**/
        /// <summary>
        /// 判断字符是否全角字符或标点
        /// </summary>
        /// <remarks>
        /// <para>全角字符 - 65248 = 半角字符</para>
        /// <para>全角空格例外</para>
        /// </remarks>
        public static bool IsSbcCase(char c)
        {
            if (c == '\u3000') return true;
            int i = (int)c - 65248;
            if (i < 32) return false;
            return IsDbcCase((char)i);
        }

        /// <summary>
        /// 过滤字符
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static string Filter(string str, char[] filter)
        {
            foreach (char c in filter)
            {
                if (str.Contains(c.ToString()))
                    str.Replace(c.ToString(), "");

            }
            return str;
        }

        public static string Last(string str, int n)
        {
            int len = str.Length;
            if (n >= len)
                return str;
            return str.Substring(len - n);
        }

        /// <summary>
        /// 判断对象是否为Int32类型的数字
        /// </summary>
        /// <param name="Expression"></param>
        /// <returns></returns>
        public static bool IsNumeric(object expression)
        {
            if (expression != null)
                return IsNumeric(expression.ToString());

            return false;

        }

        /// <summary>
        /// 判断对象是否为Int32类型的数字
        /// </summary>
        /// <param name="Expression"></param>
        /// <returns></returns>
        public static bool IsNumeric(string expression)
        {
            if (expression != null)
            {
                string str = expression;
                if (str.Length > 0 && str.Length <= 11 && Regex.IsMatch(str, @"^[-]?[0-9]*[.]?[0-9]*$"))
                {
                    if ((str.Length < 10) || (str.Length == 10 && str[0] == '1') || (str.Length == 11 && str[0] == '-' && str[1] == '1'))
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 是否是电话号码格式
        /// </summary>
        /// <param name="inputStr"></param>
        /// <returns></returns>
        public static bool IsTelephone(string inputStr)
        {

            return System.Text.RegularExpressions.Regex.IsMatch(inputStr, @"^(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$");

        }

        /// <summary>
        /// 是否是手机号码格式
        /// </summary>
        /// <param name="inputStr"></param>
        /// <returns></returns>
        public static bool IsMoblie(string inputStr)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(inputStr, @"^(?:13\d|15[89])-?\d{5}(\d{3}|\*{3})$");

        }

        /// <summary>
        /// 是否是QQ号码
        /// </summary>
        /// <returns></returns>
        public static bool IsQQNumber(string inputStr)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(inputStr, @"^[0-9]{4,14}");
        }

        /// <summary>
        /// 是否是身份证号码格式
        /// </summary>
        /// <param name="inputStr"></param>
        /// <returns></returns>
        public static bool IsIDcard(string inputStr)
        {

            return System.Text.RegularExpressions.Regex.IsMatch(inputStr, @"(^\d{18}$)|(^\d{15}$)");

        }

        /// <summary>
        /// 是否是邮政编码格式
        /// </summary>
        /// <param name="inputStr"></param>
        /// <returns></returns>
        public static bool IsPostalcode(string inputStr)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(inputStr, @"[1-9]d{5}(?!d)");
        }

        /// <summary>
        /// 是否是邮箱格式
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsEmail(string input)
        {
            string pattern = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
            return Regex.IsMatch(input, pattern);
        }

        /// <summary>
        /// 是否是Null或空白字符串
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsNullOrWhiteSpace(string input)
        {
            if (String.IsNullOrEmpty(input))
                return true;
            //string pattern = @"^(?=.*?\S)[\s\S]$";
            //return Regex.IsMatch(input, pattern);
            string str = input.Replace("　", "").Trim();
            return str.Length == 0;
        }

        /// <summary>  
        /// 生成随机字符串
        /// </summary>  
        /// <param name="length">随机字符串长度</param>  
        /// <returns>随机字符串</returns>  
        public static string CreateRandomCode(int length)
        {
            int rand;
            char code;
            string randomcode = String.Empty;
            //生成一定长度的验证码  
            System.Random random = new Random();
            for (int i = 0; i < length; i++)
            {
                rand = random.Next();
                if (rand % 3 == 0)
                {
                    code = (char)('A' + (char)(rand % 26));
                }
                else
                {
                    code = (char)('0' + (char)(rand % 10));
                }
                randomcode += code.ToString();
            }
            return randomcode;
        }

        public static string FirstChar(string str)
        {
            if (String.IsNullOrEmpty(str))
                return null;
            return str.Substring(0,1);
        }

        public static string FirstUpper(string str)
        {
            return str.Substring(0, 1).ToUpper() + str.Substring(1);
        }

        public static string TryTrim(string str)
        {
            if (str == null) return null;
            else return str.Trim();
        }

        /// <summary>
        /// 生成重复N个相同字符串组成的字符串
        /// </summary>
        /// <param name="str"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string Repetition(string str, int num)
        {
            if (num < 0)
                throw new Exception("参数num不能小于0!");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < num; i++)
            {
                sb.Append(str);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 与ASP兼容的MD5加密算法
        /// </summary>
        public static string AspMD5(string s)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(s));
            StringBuilder sb = new System.Text.StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
            {
                sb.Append(t[i].ToString("x").PadLeft(2, '0').ToUpper());
            }
            return sb.ToString();
        }

        /// <summary>
        /// 是否URL网址
        /// </summary>
        /// <param name="urlString"></param>
        /// <returns></returns>
        public static bool IsUrl(string urlString)
        {
            if (string.IsNullOrEmpty(urlString))
                return false;
            string urlFormat = @"^(http|HTTP)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$";
            //string urlFormat = @"((http)|(HTTP))://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)+(:\d+)+(/[\w- ./?%&=]*)?";
            //urlFormat = @"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&$%\$#\=~])*$";
            return Regex.IsMatch(urlString, urlFormat,RegexOptions.IgnoreCase);
        }

        /// <summary>
        /// 是否中文字符
        /// </summary>
        /// <param name="input"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static bool IsChineseLetter(string input, int index)
        {
            int code = 0;
            int chfrom = Convert.ToInt32("4e00", 16);    //范围（0x4e00～0x9fff）转换成int（chfrom～chend）
            int chend = Convert.ToInt32("9fff", 16);
            if (input != "")
            {
                code = Char.ConvertToUtf32(input, index);    //获得字符串input中指定索引index处字符unicode编码

                if (code >= chfrom && code <= chend)
                {
                    return true;     //当code在中文范围内返回true
                }
                else
                {
                    return false;    //当code不在中文范围内返回false
                }
            }
            return false;
        }

        public static bool IsChsString(string s)
        {
            bool result = false;
            for (int i = 0; i < s.Length; i++)
            {
                string mth = @"^[\u4e00-\u9fa5]+$";
                result = Regex.IsMatch(s, mth);
            }
            return result;
        }
        /// <summary>
        /// 判断是否本地路径
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsLocalPath(string str)
        {
            string patt = @"file:///[a-zA-Z]:[/a-zA-Z0-9/]+[.]?[a-zA-Z0-9_]+";
            //@"file:(//.|^/|^[a-zA-Z])?:?/.+(/$)?"
            Regex regex = new Regex(patt, RegexOptions.IgnoreCase);
            return Regex.IsMatch(str, patt);
        }
    }
}
